
package cup.modules.visual.dynamic;

import com.baomidou.dynamic.datasource.DynamicRoutingDataSource;
import com.baomidou.dynamic.datasource.creator.DataSourceCreator;
import com.baomidou.dynamic.datasource.spring.boot.autoconfigure.DataSourceProperty;
import com.baomidou.dynamic.datasource.spring.boot.autoconfigure.druid.DruidConfig;
import com.fasterxml.jackson.databind.ObjectMapper;
import cup.core.cache.utils.CacheUtil;
import cup.core.log.exception.ServiceException;
import cup.core.tool.utils.StringUtil;
import cup.modules.system.service.IDsService;
import lombok.Setter;
import lombok.val;
import org.springframework.beans.BeanUtils;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.stereotype.Component;

import javax.sql.DataSource;
import java.util.HashMap;
import java.util.Set;

/**
 * 动态数据源核心处理类
 *
 *
 */
@Component
@Setter
public class DynamicDataSourceHolder {

	private DataSource dataSource;
	private DataSourceCreator dataSourceCreator;
	private JdbcTemplate jdbcTemplate;



	/**
	 * 数据源缓存处理
	 *
	 * @param id 数据源ID
	 */
	public void handleDataSource(String id, IDsService sysClient) {
		// 获取储存的数据源集合
		DynamicRoutingDataSource ds = (DynamicRoutingDataSource) dataSource;
		Set<String> keys = ds.getCurrentDataSources().keySet();
		// 配置不存在则动态添加数据源，以懒加载的模式解决分布式场景的配置同步
		// 为了保证数据完整性，配置后生成数据源缓存，后台便无法修改更换数据源，若一定要修改请迁移数据后重启服务或自行修改底层逻辑
		if (!keys.contains(id)) {
 			DynamicDataSource dynamicDataSource = getDataSource(id,sysClient);
			if (dynamicDataSource != null) {
				// 创建数据源配置
				DataSourceProperty dataSourceProperty = new DataSourceProperty();
				// 拷贝数据源配置
				BeanUtils.copyProperties(dynamicDataSource, dataSourceProperty);
				// 设置SQL校验
				dataSourceProperty.setLazy(false);
				DruidConfig druid = dataSourceProperty.getDruid();
				if (StringUtil.equals(dataSourceProperty.getDriverClassName(), DynamicDataSourceConstant.ORACLE_DRIVER_CLASS)) {
					druid.setValidationQuery(DynamicDataSourceConstant.ORACLE_VALIDATE_STATEMENT);
				} else {
					druid.setValidationQuery(DynamicDataSourceConstant.COMMON_VALIDATE_STATEMENT);
				}
				// 创建动态数据源
				DataSource dataSource = dataSourceCreator.createDataSource(dataSourceProperty);
				// 添加最新数据源
				ds.addDataSource(id, dataSource);
			} else {
				throw new ServiceException(DynamicDataSourceConstant.DYNAMIC_DATASOURCE_NOT_FOUND);
			}
		}
	}

	/**
	 * 获取对应的数据源配置
	 *
	 * @param dsId 数据源ID
	 */
	private DynamicDataSource getDataSource(String dsId,IDsService sysClient) {
		// 获取数据源信息

		try {
			DynamicDataSource dynamicDataSource = CacheUtil.get(DynamicDataSourceConstant.DYNAMIC_DATASOURCE_CACHE, DynamicDataSourceConstant.DYNAMIC_DATASOURCE_KEY, dsId, DynamicDataSource.class, Boolean.FALSE);
			if (dynamicDataSource == null) {
				val dsR = sysClient.getById(Long.valueOf(dsId));
				val ds = dsR;
				dynamicDataSource = new DynamicDataSource();
				dynamicDataSource.setId(dsId);
				val om = new ObjectMapper();
				val params = om.readValue(ds.getParams(), HashMap.class);
				dynamicDataSource.setUrl(params.get("url").toString());
				dynamicDataSource.setUsername(params.get("user").toString());
				dynamicDataSource.setPassword(params.get("password").toString());
				dynamicDataSource.setDriverClass(params.get("driver").toString());
//				dynamicDataSource = jdbcTemplate.queryForObject(DynamicDataSourceConstant.DYNAMIC_DATASOURCE_SINGLE_STATEMENT, new String[]{dsId}, new BeanPropertyRowMapper<>(DynamicDataSource.class));
				if (dynamicDataSource != null && StringUtil.isNoneBlank(dynamicDataSource.getId(), dynamicDataSource.getDriverClass(), dynamicDataSource.getUrl(), dynamicDataSource.getUsername(), dynamicDataSource.getPassword())) {
					CacheUtil.put(DynamicDataSourceConstant.DYNAMIC_DATASOURCE_CACHE, DynamicDataSourceConstant.DYNAMIC_DATASOURCE_KEY, dsId, dynamicDataSource, Boolean.FALSE);
				}
			}
			return dynamicDataSource;
		} catch (Exception ex) {
			ex.printStackTrace();
			return null;
		}
	}

}
